#pragma once

#include <queue>
#include <atomic>
#include <mutex>
#include <condition_variable>
#include "RedisConn.h"

namespace CwRedis {

    class RedisConnPool {

    public:

        /**
          * @brief  初始化一个redis数据库连接池
          * @note   连接失败会抛出std::runtime_error
          * @param  最小连接数，最大连接数，redis连接配置
          */
        RedisConnPool(int, int, RedisConnConfig);

        /**
          * @brief  阻塞的向连接池索要一个连接的智能指针
          * @note   若连接池已销毁再申请连接，将会抛出std::runtime_error异常
          * @param  当连接池无可用连接时的执行策略
          *         is_create默认为false
          *         is_create为true时表示无可用连接时自动创建一个
          *         is_create为false时表示无可用连接时一直阻塞等待有可用连接到来
          * @retval 一个指向RedisConn实例的智能指针
          */
        std::shared_ptr<RedisConn> getConnection(bool is_create = false);

        ~RedisConnPool();

        /**
          * @brief  释放连接池内的一个连接
          * @retval 成功返回true，失败返回false
          */
        bool release();

        /**
          * @brief  获取存活连接个数
          * @retval 存活连接个数
          */
        int aliveCount() const { return alive_conn_count_; }

        RedisConnPool(RedisConnPool &) = delete;

        RedisConnPool(RedisConnPool &&) = delete;

        RedisConnPool &operator=(RedisConnPool &) = delete;

    private:

        /**
          * @brief  为连接池添加连接
          * @note   如果连接失败将会抛出std::runtime_error
          */
        void addConnection();

    private:

        // redis建立连接配置
        RedisConnConfig config_;

        // 连接池最大连接数
        unsigned short max_conn_count_;

        // 连接池最小连接数
        unsigned short min_conn_count_;

        // 连接池空闲队列
        std::queue<RedisConn *> conn_queue_;

        // 存活连接个数
        std::atomic<int> alive_conn_count_{0};

        // 连接池是否关闭
        std::atomic<bool> stop_{false};

        // 连接队列互斥锁
        std::mutex queue_locker_;

        // 条件变量
        std::condition_variable variable_;

    };

}